package com.lw.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author LW
 * @2020/8/22 9:49
 */

/**为了解决ABA问题   希望原子被动过能够知道
 * 原子引用：带版本号的原子操作AtomicReference
 */
public class AtomicReferenceDemo {

    /**AtomicStampedReference注意！！！！
     *如果泛型是一个包装类，注意对象的引用问题
     *Integer在-128~127之间赋值
     * Integer在IntegergerCache.cache产生的，会复用已有对象
     * 区间内的值可以直接使用，但是区间外的都会在堆上产生，并不会复用已有对象
     */
    public static void main(String[] args) {
        //带时间戳的
        //正常在业务操作，这里面比较的都是一个对象，对象得引用都是唯一的
        AtomicStampedReference<Integer> atomicStampedReference =
                new AtomicStampedReference<Integer>(1,1);
        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();//每次先获取目前的版本号
            System.out.println("a1==>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            /**V   expectedReference,V   newReference,
             * 期望的时间戳int expectedStamp,    新的时间戳int newStamp
             * 拿到最新的版本号，然后把最新版本号加1
             */

            System.out.println(atomicStampedReference.compareAndSet(1, 2,
                    atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
            System.out.println("a2==>"+atomicStampedReference.getStamp());
            System.out.println(atomicStampedReference.compareAndSet(2, 1,
                    atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
            System.out.println("a3==>"+atomicStampedReference.getStamp());
        },"a").start();

        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();//每次先获取目前的版本号

            System.out.println("b1-->"+stamp);
            System.out.println(atomicStampedReference.compareAndSet(1, 6,
                    stamp, stamp + 1));
            System.out.println("b2-->"+atomicStampedReference.getStamp());
        },"b").start();

    }
}
